home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
-archivi
/
-recent2
/
amhelios.lha
/
AmHelios
/
calcsub.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-31
|
6KB
|
297 lines
/* -------------------------------------------------------------------------- *\
CALCSUB.CPP
Copyright © 1997 by Jarno van der Linden
jarno@kcbbs.gen.nz
Calculation subtask for AmHelios.
Subtask handling taken from MUI Subtask.c example
This program is Freeware, and all usual Freeware rules apply.
24 Aug 1997: Project started
\* -------------------------------------------------------------------------- */
/* -------------------------------- Includes -------------------------------- */
#include "CalcSub.h"
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
/* ------------------------------ Definitions ------------------------------- */
#define STC_STARTUP -2
#define STC_SHUTDOWN -1
#define STC_START 0
#define STC_STOP 1
#define STC_SUSPEND 2
#define STC_RESUME 3
#define CALCSUB_SNAPSHOT 16
/* --------------------------------- Macros --------------------------------- */
/* -------------------------------- Typedefs -------------------------------- */
/* -------------------------------- Structs --------------------------------- */
/* ------------------------------ Proto Types ------------------------------- */
/* -------------------------------- Globals --------------------------------- */
/* ---------------------------------- Code ---------------------------------- */
SubTask::SubTask(char *name)
{
SpawnSubTask(name);
}
SubTask::~SubTask()
{
KillSubTask();
}
void SubTask::Start()
{
SendSubTaskMsg(STC_START,NULL);
}
void SubTask::Stop()
{
SendSubTaskMsg(STC_STOP,NULL);
}
void SubTask::Suspend()
{
SendSubTaskMsg(STC_SUSPEND,NULL);
}
void SubTask::Resume()
{
SendSubTaskMsg(STC_RESUME,NULL);
}
LONG SubTask::SendSubTaskMsg(WORD command,APTR params)
{
message.stm_Message.mn_ReplyPort = reply;
message.stm_Message.mn_Length = sizeof(struct SubTaskMsg);
message.stm_Command = command;
message.stm_Parameter = params;
message.stm_Result = 0;
PutMsg(command==STC_STARTUP ? &((struct Process *)task)->pr_MsgPort : port,(struct Message *)&message);
WaitPort(reply);
GetMsg(reply);
return(message.stm_Result);
}
void SubTask::SpawnSubTask(char *name)
{
if (reply = CreateMsgPort())
{
if (task = (struct Task *)CreateNewProcTags(NP_Entry,Main,NP_Name,name,NP_Priority,-2,TAG_DONE))
{
if (SendSubTaskMsg(STC_STARTUP,this))
{
return;
}
}
DeleteMsgPort(reply);
}
}
void SubTask::KillSubTask()
{
SendSubTaskMsg(STC_SHUTDOWN,NULL);
DeleteMsgPort(reply);
}
/* the following functions are called from the sub task */
void SubTask::ExitSubTask(SubTask *thisst,struct SubTaskMsg *stm)
{
/*
** We reply after a Forbid() to make sure we're really gone
** when the main task continues.
*/
if (thisst->port)
DeleteMsgPort(thisst->port);
Forbid();
stm->stm_Result = FALSE;
ReplyMsg((struct Message *)stm);
}
SubTask *SubTask::InitSubTask(void)
{
struct Task *me = FindTask(NULL);
SubTask *thisst;
struct SubTaskMsg *stm;
/*
** Wait for our startup message from the SpawnSubTask() function.
*/
WaitPort(&((struct Process *)me)->pr_MsgPort);
stm = (struct SubTaskMsg *)GetMsg(&((struct Process *)me)->pr_MsgPort);
thisst = (SubTask *)stm->stm_Parameter;
if (thisst->port = CreateMsgPort())
{
/*
** Reply startup message, everything ok.
** Note that if the initialization fails, the code falls
** through and replies the startup message with a stm_Result
** of 0 after a Forbid(). This tells SpawnSubTask() that the
** sub task failed to run.
*/
stm->stm_Result = TRUE;
ReplyMsg((struct Message *)stm);
return(thisst);
}
else
{
ExitSubTask(thisst,stm);
return(NULL);
}
}
void __asm __saveds SubTask::Main(void)
{
SubTask *thisst;
if(thisst = InitSubTask())
{
BOOL running = TRUE;
BOOL worktodo = FALSE;
BOOL suspended = FALSE;
struct SubTaskMsg *stm;
for(;;)
{
while(stm = (struct SubTaskMsg *)GetMsg(thisst->port))
{
switch(stm->stm_Command)
{
case STC_SHUTDOWN:
running = FALSE;
break;
case STC_START:
worktodo = TRUE;
thisst->StartFunc();
break;
case STC_STOP:
worktodo = FALSE;
thisst->StopFunc();
break;
case STC_SUSPEND:
suspended = TRUE;
break;
case STC_RESUME:
suspended = FALSE;
break;
default:
stm->stm_Result = thisst->HandleMessage(stm->stm_Command,stm->stm_Parameter);
break;
}
if(!running)
break;
ReplyMsg((struct Message *)stm);
}
if(!running)
break;
if((worktodo) && (!suspended))
{
worktodo = thisst->SubFunc();
if(!worktodo)
thisst->StopFunc();
}
else
{
WaitPort(thisst->port);
}
}
if(worktodo)
thisst->StopFunc();
ExitSubTask(thisst,stm);
}
}
CalcSub::CalcSub(char *name,RadEqnSolve *radiosity_arg,Environ *env_arg)
: SubTask(name)
{
#if (defined(_HEMI_CUBE) || defined(_CUBIC_TETRA))
radiosity = (ProgRad *)radiosity_arg;
#elif defined(_RAY_CAST)
radiosity = (RayRad *)radiosity_arg;
#else
radiosity = radiosity_arg;
#endif
env = env_arg;
}
void CalcSub::Snapshot()
{
SendSubTaskMsg(CALCSUB_SNAPSHOT,NULL);
}
void CalcSub::StartFunc()
{
radiosity->Open(env);
}
BOOL CalcSub::SubFunc()
{
return !(radiosity->Calculate());
}
void CalcSub::StopFunc()
{
radiosity->Close();
}
void CalcSub::SnapshotFunc()
{
radiosity->Snapshot();
}
LONG CalcSub::HandleMessage(WORD command,APTR parameter)
{
switch(command)
{
case CALCSUB_SNAPSHOT:
SnapshotFunc();
break;
}
return 0;
}